﻿using Sidvall.WorkItemManager.Data;
using System.Threading.Tasks;

namespace Sidvall.WorkItemManager.Workflow
{
    public abstract class WorkItemProviderBase : IWorkItemProvider
    {
        #region Public Members

        public IWorkItemProviderManager Manager { get; set; }
        public SensorValueCollection SensorValues { get; private set; }
        public string Context { get; set; }
        public string ExecutionContext { get; set; }
        public byte ExecutionCompletionPercentage { get; private set; }
        public bool IsCanceled { get; private set; }

        public abstract Task<WorkItemResult> ExecuteAsync();

        #region GetSensorsAsync

        public virtual Task<SensorCollection> GetSensorsAsync()
        {
            var items = new SensorCollection();
            return Task.FromResult(items);
        }

        #endregion
        #region GetWorkItemRatingAsync

        public virtual Task<WorkItemRating> GetWorkItemRatingAsync()
        {
            var item = new WorkItemRating(WorkItemRatingType.Excellent);
            return Task.FromResult(item);
        }

        #endregion

        #region UpdateExecutionContextAsync

        public async Task UpdateExecutionContextAsync(string context, byte executionCompletionPercentage)
        {
            this.ExecutionContext = context;
            this.ExecutionCompletionPercentage = executionCompletionPercentage;
            var args = new WorkItemProviderEventArgs()
            {
                EventType = WorkItemEventType.ExecutionContextChanged,
            };
            args = await ProcessEventAsync(args).ConfigureAwait(false);
            if (args.Cancel)
                this.IsCanceled = true;
        }

        #endregion
        #region UpdateSensorsAsync

        public async Task UpdateSensorsAsync()
        {
            if (this.SensorValues.Count == 0)
                return;
            var args = new WorkItemProviderEventArgs()
            {
                EventType = WorkItemEventType.SensorsChanged,
            };
            foreach (var sensor in this.SensorValues)
                args.Sensors.Add(sensor);
            args = await ProcessEventAsync(args).ConfigureAwait(false);
            if (args.Cancel)
                this.IsCanceled = true;
        }

        #endregion

        #region ProcessEventAsync

        protected async Task<WorkItemProviderEventArgs> ProcessEventAsync(WorkItemProviderEventArgs args)
        {
            if (args == null)
            {
                args = new WorkItemProviderEventArgs()
                {
                    EventType = WorkItemEventType.ExecutionContextChanged,
                };
            }
            args.Provider = this;
            if (this.Manager != null)
                await this.Manager.ProcessEventAsync(args).ConfigureAwait(false);
            return args;
        }

        #endregion

        #endregion
        #region Constructors

        protected WorkItemProviderBase()
        {
            this.SensorValues = new SensorValueCollection();
        }

        #endregion
    }
}
